package com.shelpe.services.tenant.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shelpe.services.tenant.dto.ForbiddenCategoryDto;
import com.shelpe.services.tenant.dto.ForbiddenWordDto;
import com.shelpe.services.tenant.dto.ViolationDetectionDto;
import com.shelpe.services.tenant.model.Auth;
import com.shelpe.services.tenant.model.Products;
import com.shelpe.services.tenant.model.Users;
import com.shelpe.services.tenant.mongomodel.ForbiddenCategory;
import com.shelpe.services.tenant.mongomodel.ForbiddenWord;
import com.shelpe.services.tenant.service.AuthService;
import com.shelpe.services.tenant.service.ForbiddenCategoryService;
import com.shelpe.services.tenant.service.ForbiddenWordService;
import com.shelpe.services.tenant.service.ProductService;
import com.shelpe.services.tenant.service.UserService;
import com.shelpe.services.tenant.service.ViolationDetectionService;

@RestController
@RequestMapping(value="/jobserver")
public class ViolationDetectionController {
	
	private static final Logger logger = LoggerFactory.getLogger(ViolationDetectionController.class);
	
	@Autowired
	private ForbiddenWordService forbiddenWordService;
	
	@Autowired
	private ForbiddenCategoryService forbiddenCategoryService;
	
	@Autowired
	private UserService userService;
	
	@Autowired
	private ProductService productService;
	
	@Autowired
	private ViolationDetectionService detectService;
	
	@Autowired
	private AuthService authService;
	
	@Value("${jobserver.mainInnerUserId}")
	private String mainInnerUserId;
	
	private final ExecutorService executor = Executors.newSingleThreadExecutor();
	
	@RequestMapping("/forbiddenword")
	@ResponseBody
	public ForbiddenWordDto addNewForbiddenWord(@RequestParam("forbiddenword") String forbiddenWord){
		
		ForbiddenWordDto dto = new ForbiddenWordDto();
		ForbiddenWord word = new ForbiddenWord();
		
		word.setWord(forbiddenWord);
		forbiddenWordService.saveForbiddenWord(word);
		dto.setMessage("success");
		
		return dto;
	}
	
	@RequestMapping("/forbiddencategory")
	@ResponseBody
	public ForbiddenCategoryDto addNewForbiddenCategory(@RequestParam("forbiddencategory") String forbiddenCategory, 
			@RequestParam(value = "propsname", required = false) String propsName){
		
		ForbiddenCategoryDto dto = new ForbiddenCategoryDto();
		ForbiddenCategory category = new ForbiddenCategory();
		
		category.setCategory(forbiddenCategory);
		category.setPropsName(propsName);
		forbiddenCategoryService.saveForbiddenCategory(category);
		dto.setMessage("success");
		
		return dto;
	}
	
	@RequestMapping("/violationdetection")//异步接口
	@ResponseBody
	public ViolationDetectionDto detect(){
		
		ViolationDetectionDto dto = new ViolationDetectionDto();
		
		
		CompletionService<ViolationDetectionDto> comletionService = new ExecutorCompletionService<ViolationDetectionDto>(executor); 
		
		comletionService.submit(new Callable<ViolationDetectionDto>(){

			@Override
			public ViolationDetectionDto call() throws Exception {
				// TODO Auto-generated method stub
				List<Users> users = userService.getAllUsers();
				List<Users> filterUsers = filterUser(users);
				
				if(filterUsers != null && filterUsers.size() > 0){
					
					Iterable<ForbiddenWord> itWords = forbiddenWordService.getAllForbiddenWordsIter();
					Iterable<ForbiddenCategory> itCategories = forbiddenCategoryService.getAllForbiddenCategoriesIter();
					
					for(Users user : users){
						
						Long userId =  user.getUserId();
						if(userId < 0){
							continue;
						}
						
						List<Products> products = productService.getItemsByUserId(userId);
						
						if(products != null && products.size() > 0){
							for(Products product : products){
								
								JSONObject forbiddenResult = new JSONObject();
								JSONArray forbiddenWord = detectService.forbiddenWordDetect(product, itWords);
								JSONArray forbiddenCategory = null;
								
								if(product.getCid() != 0){
									forbiddenCategory = detectService.forbiddenCategoryDetect(product, itCategories); 
								}
								
								if(forbiddenWord != null && forbiddenWord.size() > 0){
									
									forbiddenResult.put("forbidden_word", forbiddenWord);
								}
								
								if(forbiddenCategory != null && forbiddenCategory.size() > 0){
									
									forbiddenResult.put("forbidden_category", forbiddenCategory);
								}
								
								if(!forbiddenResult.isEmpty()){
									product.setDetectResult(1);
									product.setDetectDetail(forbiddenResult.toJSONString());
									logger.info("detect result numiid: {}, violation: {}", product.getNumIid(), product.getDetectDetail());
									productService.updateItems(product);
								}else{
									Integer oldResult = product.getDetectResult();
									if(oldResult != null && oldResult > 0){
										product.setDetectResult(0);
										product.setDetectDetail(null);
										logger.info("detect result numiid: {} changed to normal", product.getNumIid());
										productService.updateItems(product);
									}
								}
							}//for every product
						}
					}//for every user
				}
				
				return null;
			}
		});
		
		dto.setMessage("success");
		
		return dto;
	}
	
	
	private List<Users> filterUser(List<Users> list){
		
		List<Long> innerUserIdList = new ArrayList<Long>();
		if(mainInnerUserId != null){
			String[] innerUserId = mainInnerUserId.split(",");

			if(innerUserId != null && innerUserId.length > 0){
				for(int i = 0; i < innerUserId.length; i++){
					innerUserIdList.add(Long.valueOf(innerUserId[i]));
				}
			}
		}

		List<Users> temp = new ArrayList<Users>();
		if(list != null && list.size() > 0){
			
			for(Users user : list){
				Long userId = user.getUserId();
				Long authorizedTo = user.getAuthorizedTo();
				
				if(userId > 0 || innerUserIdList.contains(authorizedTo)){
					temp.add(user);
				}else{
					List<Auth> authList = authService.getAuthByUserId(userId);
					if(authList != null && authList.size() > 0){
						temp.add(user);
					}
				}
			}
		}
		return temp;
	}
}
